package com.xctech.yace.swing.tab;

import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.serializer.SerializerFeature;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.google.gson.Gson;
import com.xctech.yace.pojo.Auth;
import com.xctech.yace.service.FileService;
import com.xctech.yace.swing.ConfigValue;
import com.xctech.yace.swing.FatherSwing;
import com.xctech.yace.swing.InitFileConfig;
import com.xctech.yace.swing.component.ComboboxToolTipRenderer;
import com.xctech.yace.util.*;

import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import static javax.swing.JOptionPane.*;

public class ConversionSwing extends FatherSwing implements ConfigValue, InitFileConfig {

    public static String title = "转换";

    public static JPanel genConvertPanel() {
        //转换画板
        JPanel convert = new JPanel();

        /*
         * 调用用户定义的方法并添加组件到面板
         */
        placeComponents(convert);

        return convert;
    }

    private static void placeComponents(JPanel panel) {
        /* 布局部分我们这边不多做介绍
         * 这边设置布局为 null
         */
        panel.setLayout(null);

        //增加模板
        JComboBox addModelBox=new JComboBox();    //创建JComboBox
        addModelBox.addItem("------------------------------------------------添加模板--------------------------------");    //向下拉列表中添加一项
        modelMapSql.entrySet().stream().forEach(model->{
            addModelBox.addItem(model.getKey());
        });
        addModelBox.setBounds(15,20,sfiledW+330,height);
        addModelBox.setToolTipText("直接选中即添加到到消息框中...");
        panel.add(addModelBox);

        ComboboxToolTipRenderer renderer = new ComboboxToolTipRenderer();
        addModelBox.setRenderer(renderer);


        // 生成按钮
        JButton genButton = new JButton("全部生成");
        genButton.setBounds(460,20,sfiledW,height);
        genButton.setToolTipText("全部生成");
        panel.add(genButton);

        //搜索文本框
        JTextField mixText = new JTextField(20);
        mixText.setBounds(630,20,200,height);
        mixText.setFont(new Font("Courier",Font.BOLD,13));
        mixText.setToolTipText("加密盐值");
        panel.add(mixText);

        //message按钮
        JTextArea convertFrom = new JTextArea();
        JScrollPane scrollArea = new JScrollPane(convertFrom);

        scrollArea.setMaximumSize(scrollArea.getPreferredSize());
        scrollArea.setBounds(15,20+height+space,800,870);
        convertFrom.setFont(new Font("幼圆",Font.BOLD,12));

        scrollArea.setHorizontalScrollBarPolicy(
                JScrollPane.HORIZONTAL_SCROLLBAR_ALWAYS);
        scrollArea.setVerticalScrollBarPolicy(
                JScrollPane.VERTICAL_SCROLLBAR_ALWAYS);
        panel.add(scrollArea);

        //按钮 To json
        JButton leftButton = new JButton("TJ->");
        leftButton.setBounds(835,400,65,height);
        panel.add(leftButton);

        //按钮 R json
        JButton rightButton = new JButton("<-RJ");
        rightButton.setBounds(835,450,65,height);
        panel.add(rightButton);

        //生成 >>>
        JButton genSqlButton = new JButton("G->");
        genSqlButton.setBounds(835,500,65,height);
        panel.add(genSqlButton);

        //加
        JButton tradeEncryptButton = new JButton("<-T密");
        tradeEncryptButton.setBounds(835,550,65,height);
        panel.add(tradeEncryptButton);

        //解
        JButton tradeDecryptButton = new JButton("R解->");
        tradeDecryptButton.setBounds(835,600,65,height);
        panel.add(tradeDecryptButton);

        //转换后message
        JTextArea convertTo = new JTextArea();
        JScrollPane scrollArea1 = new JScrollPane(convertTo);

        scrollArea1.setMaximumSize(scrollArea1.getPreferredSize());
        scrollArea1.setBounds(915,20+height+space,850,870);
        convertTo.setFont(new Font("幼圆",Font.BOLD,15));

        scrollArea1.setHorizontalScrollBarPolicy(
                JScrollPane.HORIZONTAL_SCROLLBAR_ALWAYS);
        scrollArea1.setVerticalScrollBarPolicy(
                JScrollPane.VERTICAL_SCROLLBAR_ALWAYS);
        panel.add(scrollArea1);

        leftButton.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                //清空右
                convertTo.setText("");
                String msg = convertFrom.getText().trim();
                try{
                    JSONObject jsonObject = JSONObject.parseObject(msg);
                    convertTo.setText(FormatUtil.format(jsonObject.toJSONString(jsonObject, SerializerFeature.WriteMapNullValue)));
                }catch (Exception ex){
                    String[] msgs = msg.split("\n");
                    String m0 = msgs[0];
                    String m1 = msgs[1];
                    JSONObject j0 = JSONObject.parseObject(m0);
                    JSONObject j1 = JSONObject.parseObject(m1);
                    Map<String, Object> diffJson = JSONUtil.diffPayload(j0, j1);
                    JSONObject jsonObject = new JSONObject(diffJson);
                    convertTo.setText(FormatUtil.format(jsonObject.toJSONString(jsonObject, SerializerFeature.WriteMapNullValue)));
                }
            }
        });

        rightButton.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                //清空左
                convertFrom.setText("");
                String msg = convertTo.getText().trim();
                JSONObject jsonObject = JSONObject.parseObject(msg);
                convertFrom.setText(jsonObject.toJSONString(jsonObject, SerializerFeature.WriteMapNullValue));
            }
        });

        tradeEncryptButton.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                encryptDeal(convertFrom, mixText, convertTo);
            }
        });

        tradeDecryptButton.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                decryptDeal(convertTo, convertFrom, mixText);
            }
        });

        genSqlButton.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                convertTo.setText("");
                String msg = convertFrom.getText().trim();
                JSONObject jsonObject = JSONObject.parseObject(msg);
                convertTo.setText(JSONUtil.gensql("TABLE",jsonObject));
            }
        });

        convertFrom.addKeyListener(new KeyAdapter() {
            @Override
            public void keyPressed(KeyEvent e) {
                if(e.getKeyCode() == KeyEvent.VK_DELETE){
                    System.out.println("清空convertFrom界面");
                    convertFrom.setText("");
                }
            }
        });

        convertTo.addKeyListener(new KeyAdapter() {
            @Override
            public void keyPressed(KeyEvent e) {
                if(e.getKeyCode() == KeyEvent.VK_DELETE){
                    System.out.println("清空convertTo界面");
                    convertTo.setText("");
                }
            }
        });

        //
        genButton.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                String fileName = String.valueOf(System.currentTimeMillis()) + ".sql";
                for(Map.Entry<String, String> entry:modelMapSql.entrySet()){
                    String tableName = entry.getKey();
                    String[] topics = tableName.split("#");
                    if(topics.length >= 2){
                        tableName = topics[1];
                    }
                    String sql = JSONUtil.gensql(tableName, JSONObject.parseObject(entry.getValue()));
                    FileService.saveSqlFile(fileName,sql+";");
                }
                JOptionPane.showMessageDialog(null, "成功", "成功", INFORMATION_MESSAGE);
            }
        });

        addModelBox.addItemListener(new ItemListener() {
            @Override
            public void itemStateChanged(ItemEvent e) {
                if(e.getStateChange() == ItemEvent.SELECTED){
                    if(addModelBox.getSelectedIndex()!=0){
                        String modelKey = addModelBox.getSelectedItem().toString().trim();;
                        String[] msgs = modelMapSql.get(modelKey).split("#{5,}");
                        for(int i = 0;i < msgs.length;i++){
                            String msg = msgs[i];
                            JSONObject jsonObject = JSONObject.parseObject(msg);
                            convertFrom.append(FormatUtil.format(JSONObject.toJSONString(jsonObject, SerializerFeature.WriteMapNullValue))+"\n");
                        }
                    }
                }
            }
        });
    }

    private static void decryptDeal(JTextArea convertTo, JTextArea convertFrom, JTextField mixText) {
        try{
            //清空左
            convertTo.setText("");
            String msg = convertFrom.getText().trim();
            if("".equals(msg) || msg == null){
                JOptionPane.showMessageDialog(null,
                        "<<右>>文本msg为空,请检查","Warning",WARNING_MESSAGE);
                System.out.println("<<右>>文本msg为空,请检查");
                return;
            }
            if(msg.startsWith("ENC(")){
                String jasyptPw = mixText.getText().trim();
                if("".equals(jasyptPw) || jasyptPw == null){
                    JOptionPane.showMessageDialog(null,
                            "文本盐值jasyptPw为空,请检查","Warning",WARNING_MESSAGE);
                    System.out.println("文本盐值jasyptPw为空,请检查");
                    return;
                }
                String s = JasyptUtils.decryptText(jasyptPw, msg);
                convertTo.setText(s);
                return;
            }
            Map<String, String> map = new HashMap<>();
            String json = DeflaterUtils.unzipString(msg);
            ObjectMapper mapper = new ObjectMapper();
            List<Auth> auths = mapper.readValue(json,  new TypeReference<List<Auth>>(){});
            for (Auth auth:auths) {
                map.put(auth.getConfigTag(),
                        JasyptUtils.decryptText(
                                Auth.decryptMix(auth.getMixCipher(), Auth.MD5LEN, Auth.SPLIT).f1,
                                auth.getCipher()));
            }
            String jsonString = JSONObject.toJSONString(map);
            convertTo.setText(FormatUtil.format(jsonString));
            mixText.setText("");
        }catch (Exception exception){
            JOptionPane.showMessageDialog(null,
                    "解密失败,请检查密文和盐值","Warning",WARNING_MESSAGE);
            exception.printStackTrace();
        }
    }

    private static void encryptDeal(JTextArea convertFrom, JTextField mixText, JTextArea convertTo) {
        try {
            //清空左
            convertFrom.setText("");
            String jasyptPw = mixText.getText().trim();
            if("".equals(jasyptPw) || jasyptPw == null){
                JOptionPane.showMessageDialog(null,
                        "文本盐值jasyptPw为空,请检查","Warning",WARNING_MESSAGE);
                System.out.println("文本盐值jasyptPw为空,请检查");
                return;
            }
            String msg = convertTo.getText().trim();
            if("".equals(msg) || msg == null){
                JOptionPane.showMessageDialog(null,
                        "<<左>>文本msg为空,请检查","Warning",WARNING_MESSAGE);
                System.out.println("<<左>>文本msg为空,请检查");
                return;
            }
            if(msg.startsWith("ENC(")){
                String s = msg.substring(msg.indexOf("ENC(")+4,msg.lastIndexOf(")"));
                String s1 = JasyptUtils.encryptText(jasyptPw, s);
                convertFrom.setText(s1);
                return;
            }
            Map<String,String> map = JSONObject.parseObject(msg, Map.class);
            ArrayList<Auth> auths = new ArrayList<>();
            for (Map.Entry<String, String> entry :map.entrySet()) {
                String key = entry.getKey();
                String value = entry.getValue();
                Auth auth = new Auth();
                auth.setID(auths.size()+1);
                auth.setConfigTag(key.trim());
                auth.setCipher(JasyptUtils.encryptText(jasyptPw,value));
                auth.setMixCipher(Auth.encryptMix(value,jasyptPw,Auth.SPLIT));
                auths.add(auth);
            }
            ObjectMapper mapper = new ObjectMapper();
            String zipMsg = DeflaterUtils.zipString(mapper.writeValueAsString(auths));
            convertFrom.setText(zipMsg);
        } catch (JsonProcessingException ex) {
            JOptionPane.showMessageDialog(null,
                    "加密失败,简单加密请检查ENC(明文)格式和盐值","Warning",WARNING_MESSAGE);
            ex.printStackTrace();
        }
    }


}
